Skip to content

Upgrade ios packages and update contract#338

Merged
dishit-wednesday merged 3 commits into
mainfrom
upgrade-ios-packages-and-update-contract
May 7, 2026
Merged

Upgrade ios packages and update contract#338
dishit-wednesday merged 3 commits into
mainfrom
upgrade-ios-packages-and-update-contract

Conversation

@dishit-wednesday

Copy link
Copy Markdown
Collaborator

Summary

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (code change that neither fixes a bug nor adds a feature)
  • Chore (build process, CI, dependency updates, etc.)

Screenshots / Screen Recordings

Android

Before After

iOS

Before After

Checklist

General

  • My code follows the project's coding style and conventions
  • I have performed a self-review of my code
  • I have added/updated comments where the logic isn't self-evident
  • My changes generate no new warnings or errors

Testing

  • I have tested on Android (physical device or emulator)
  • I have tested on iOS (physical device or simulator)
  • I have tested in light mode and dark mode
  • Existing tests pass locally (npm test)
  • I have added tests that prove my fix is effective or my feature works

React Native Specific

  • No new native module without corresponding platform implementation (Android + iOS)
  • New native modules are added to the Xcode project build target (project.pbxproj)
  • No hardcoded pixel values — uses SPACING / TYPOGRAPHY constants from the theme
  • Styles use useThemedStyles pattern (not inline or static StyleSheet.create)
  • Animations/gestures work smoothly on both platforms
  • Large lists use FlatList / FlashList (not .map() inside ScrollView)
  • No unnecessary re-renders introduced (check with React DevTools Profiler if unsure)

Performance & Models

  • Downloads / long-running tasks report progress to the UI
  • File paths are resolved correctly on both platforms (no hardcoded / vs \\)
  • Large files (models, assets) are not committed to the repository

Security

  • No secrets, API keys, or credentials are included in the code
  • User input is validated/sanitized where applicable

Related Issues

Additional Notes

dishit-wednesday and others added 2 commits May 7, 2026 11:28
Co-authored-by: Dishit <hanmadishit74@gmail.com>
Co-authored-by: Dishit <hanmadishit74@gmail.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several new fields—modelKey, modelType, combinedTotalBytes, and metadataJson—to the iOS DownloadManagerModule to mirror Android's WorkManager columns and ensure consistent JS hydration across platforms. Additionally, the llama-rn dependency is updated, and the TypeScript background download service is adjusted to support the new downloadId property. Feedback was provided regarding an inconsistent default value for modelType in the DownloadManagerModule extension, which should be aligned with other parts of the module to maintain a consistent data contract.

Comment thread ios/DownloadManagerModule.swift Outdated
status: "running",
startedAt: Date().timeIntervalSince1970 * 1000,
modelKey: params["modelKey"] as? String,
modelType: (params["modelType"] as? String) ?? "image",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The default value for modelType is set to "image" here, which is inconsistent with startDownload (line 558), the restoration logic (line 499), and the decoding logic (line 158), all of which default to "text". To ensure a consistent data contract across the module and with the JavaScript service, this should default to "text".

Suggested change
modelType: (params["modelType"] as? String) ?? "image",
modelType: (params["modelType"] as? String) ?? "text",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — changed default to "text" to be consistent with startDownload, the persistence decoder, and restoreTasksFromSession. JS always passes modelType explicitly for multifile downloads so the default never fired in practice, but the inconsistency has been resolved.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several new fields (modelKey, modelType, combinedTotalBytes, and metadataJson) to the iOS DownloadManagerModule to ensure cross-platform consistency with Android and improve JavaScript hydration. It also updates the llama-rn dependency and adjusts the background download service to support the new downloadId property. Feedback was provided regarding potential state loss during task restoration, suggesting these fields be stored in TaskDescription for better recovery. Additionally, an inconsistency in the default value for modelType across different initialization paths was identified.

Comment on lines +498 to +501
modelKey: nil,
modelType: "text",
combinedTotalBytes: 0,
metadataJson: nil,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

These new fields are being initialized with hardcoded defaults during task restoration. If the app's persisted state in UserDefaults is lost or out of sync, but background URLSessionTasks are still active, the restored DownloadInfo will lose its original modelKey, modelType, combinedTotalBytes, and metadataJson. To ensure robustness and avoid swallowing the state-loss issue with defaults, these fields should be added to the TaskDescription struct so they can be recovered directly from the URLSessionDownloadTask.taskDescription property.

References
  1. Instead of swallowing errors by only logging them, functions that can fail should propagate the result (e.g., by returning a success/failure status or throwing an error) to allow callers to handle it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. Adding these fields to TaskDescription is the more robust solution for the edge case where URLSession tasks survive but UserDefaults is wiped. In practice these always travel together on iOS — if UserDefaults is cleared the session tasks are invalidated too. We've accepted this as a known limitation given the added complexity of expanding TaskDescription encoding. The decodeIfPresent fallbacks protect the common upgrade path.

Comment thread ios/DownloadManagerModule.swift Outdated
status: "running",
startedAt: Date().timeIntervalSince1970 * 1000,
modelKey: params["modelKey"] as? String,
modelType: (params["modelType"] as? String) ?? "image",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The default value for modelType here is "image", whereas in startDownload (line 558) and restoreTasksFromSession (line 499) it defaults to "text". This inconsistency can lead to unexpected behavior. Consider using a consistent default or ensuring the type is explicitly passed from the JavaScript side.

Suggested change
modelType: (params["modelType"] as? String) ?? "image",
modelType: (params["modelType"] as? String) ?? "text",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — changed default to "text" to match startDownload and the rest of the module.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several new fields (modelKey, modelType, combinedTotalBytes, and metadataJson) to the iOS DownloadManagerModule to align with the Android implementation and support cross-platform JS hydration. It also updates the llama-rn dependency and adjusts the TypeScript service to handle the new downloadId field. Feedback identified a potential race condition in download ID generation, inconsistent default values for modelType across different methods, and a naming mismatch for the creation timestamp compared to the Android and TypeScript implementations.

Comment thread ios/DownloadManagerModule.swift Outdated
Comment on lines 561 to 562
let downloadId = String(nextDownloadId)
nextDownloadId += 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The nextDownloadId is being accessed and incremented outside of the synchronized queue. Since this module uses a concurrent queue for state management and can be called from multiple threads via the React Native bridge, this creates a race condition that could lead to duplicate downloadId values.

Suggested change
let downloadId = String(nextDownloadId)
nextDownloadId += 1
let downloadId = queue.sync(flags: .barrier) {
let id = String(nextDownloadId)
nextDownloadId += 1
return id
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — nextDownloadId read and increment are now wrapped in queue.sync(flags: .barrier) matching the rest of the module's state management pattern.

Comment thread ios/DownloadManagerModule.swift Outdated
Comment on lines +771 to +773
"startedAt": NSNumber(value: info.startedAt),
"modelType": info.modelType,
"combinedTotalBytes": NSNumber(value: info.combinedTotalBytes)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The iOS implementation returns the timestamp as startedAt, but the TypeScript service (line 90) and the Android implementation use createdAt. To ensure cross-platform compatibility and correct hydration in the JS layer, it is recommended to include the createdAt key in the response.

          "startedAt": NSNumber(value: info.startedAt),
          "createdAt": NSNumber(value: info.startedAt),
          "modelType": info.modelType,
          "combinedTotalBytes": NSNumber(value: info.combinedTotalBytes)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — getActiveDownloads now includes a createdAt key aliased from startedAt so the JS mapper receives the correct field name on both platforms.

Comment thread ios/DownloadManagerModule.swift Outdated
status: "running",
startedAt: Date().timeIntervalSince1970 * 1000,
modelKey: params["modelKey"] as? String,
modelType: (params["modelType"] as? String) ?? "image",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The default modelType here is set to "image", which is inconsistent with startDownload (line 558), the persistence decoder (line 158), and the session restoration logic (line 499), all of which default to "text". This inconsistency can lead to models being incorrectly categorized depending on the download method used or after an app restart.

Suggested change
modelType: (params["modelType"] as? String) ?? "image",
modelType: (params["modelType"] as? String) ?? "text",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — changed default to "text" for consistency across the module.

@codecov

codecov Bot commented May 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.31%. Comparing base (8a18763) to head (a786187).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #338      +/-   ##
==========================================
- Coverage   82.32%   82.31%   -0.02%     
==========================================
  Files         231      231              
  Lines       11900    11901       +1     
  Branches     3265     3266       +1     
==========================================
- Hits         9797     9796       -1     
  Misses       1246     1246              
- Partials      857      859       +2     
Files with missing lines Coverage Δ
src/services/backgroundDownloadService.ts 80.53% <100.00%> (+0.17%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sonarqubecloud

sonarqubecloud Bot commented May 7, 2026

Copy link
Copy Markdown

@dishit-wednesday

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the DownloadManagerModule in iOS to include new fields (modelKey, modelType, combinedTotalBytes, and metadataJson) for better alignment with Android's WorkManager and improved JS hydration. It also introduces thread-safe generation of downloadId using a barrier queue. Additionally, the llama-rn dependency is updated in Podfile.lock, and the TypeScript backgroundDownloadService is adjusted to handle the updated download ID field. I have no feedback to provide.

@dishit-wednesday dishit-wednesday merged commit 55dc623 into main May 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant